package anyVehicle;

import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import net.minecraft.client.Minecraft;
import net.minecraft.src.AxisAlignedBB;
import net.minecraft.src.Block;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.EntityRenderer;
import net.minecraft.src.EntitySorter;
import net.minecraft.src.EnumMovingObjectType;
import net.minecraft.src.GLAllocation;
import net.minecraft.src.ICamera;
import net.minecraft.src.IWorldAccess;
import net.minecraft.src.ItemStack;
import net.minecraft.src.MathHelper;
import net.minecraft.src.MovingObjectPosition;
import net.minecraft.src.OpenGlCapsChecker;
import net.minecraft.src.RenderBlocks;
import net.minecraft.src.RenderEngine;
import net.minecraft.src.RenderGlobal;
import net.minecraft.src.RenderHelper;
import net.minecraft.src.RenderList;
import net.minecraft.src.RenderSorter;
import net.minecraft.src.Tessellator;
import net.minecraft.src.TileEntity;
import net.minecraft.src.WorldRenderer;

import org.lwjgl.opengl.ARBOcclusionQuery;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector4f;

public class VehicleRenderGlobal implements IWorldAccess {
    public List tileEntities;
    public Vehicle entityVehicle;
    public VehicleBlocks worldObj;
    public RenderEngine renderEngine;
    private List worldRenderersToUpdate;
    private WorldRenderer sortedWorldRenderers[];
    private WorldRenderer worldRenderers[];
    private int renderChunksWide;
    private int renderChunksTall;
    private int renderChunksDeep;
    private int glRenderListBase;
    public Minecraft mc;
    public RenderBlocks globalRenderBlocks;
    private IntBuffer glOcclusionQueryBase;
    private boolean occlusionEnabled;
    private int starGLCallList;
    private int minBlockX;
    private int minBlockY;
    private int minBlockZ;
    private int maxBlockX;
    private int maxBlockY;
    private int maxBlockZ;
    private int renderDistance;
    private int renderEntitiesStartupCounter;
    private int countEntitiesTotal;
    private int countEntitiesRendered;
    private int countEntitiesHidden;
    int dummyBuf50k[];
    IntBuffer occlusionResult;
    private int renderersLoaded;
    private int renderersBeingClipped;
    private int renderersBeingOccluded;
    private int renderersBeingRendered;
    private int renderersSkippingRenderPass;
    private int worldRenderersCheckIndex;
    private List glRenderLists;
    private RenderList allRenderLists[] = {
        new RenderList(), new RenderList(), new RenderList(), new RenderList()
    };
    double prevSortX;
    double prevSortY;
    double prevSortZ;
    public float damagePartialTime;
    int frustrumCheckOffset;
	private RenderGlobal renderGlobal;


	public VehicleRenderGlobal(Minecraft minecraft, RenderEngine renderengine, Vehicle e) {
		this.renderGlobal = minecraft.renderGlobal;
        tileEntities = new ArrayList();
        worldRenderersToUpdate = new ArrayList();
        occlusionEnabled = false;
        renderDistance = -1;
        renderEntitiesStartupCounter = 2;
        dummyBuf50k = new int[50000];
        occlusionResult = GLAllocation.createDirectIntBuffer(64);
        glRenderLists = new ArrayList();
        prevSortX = -9999D;
        prevSortY = -9999D;
        prevSortZ = -9999D;
        frustrumCheckOffset = 0;
        mc = minecraft;
        renderEngine = renderengine;
        byte byte0 = 64;
        glRenderListBase = GLAllocation.generateDisplayLists(byte0 * byte0 * byte0 * 3);
        occlusionEnabled = OpenGlCapsChecker.checkARBOcclusion();
        if(occlusionEnabled)
        {
            occlusionResult.clear();
            glOcclusionQueryBase = GLAllocation.createDirectIntBuffer(byte0 * byte0 * byte0);
            glOcclusionQueryBase.clear();
            glOcclusionQueryBase.position(0);
            glOcclusionQueryBase.limit(byte0 * byte0 * byte0);
            ARBOcclusionQuery.glGenQueriesARB(glOcclusionQueryBase);
        }
        starGLCallList = GLAllocation.generateDisplayLists(3);

		setEntity(e);
        
	}

    public void setEntity(Vehicle ecs)
    {
    	entityVehicle = ecs;
    	
        if(worldObj != null)
        {
            worldObj.removeWorldAccess(this);
        }
        prevSortX = -9999D;
        prevSortY = -9999D;
        prevSortZ = -9999D;
//        RenderManager.instance.set(world);
        worldObj = ecs.vehicleBlocks;
        globalRenderBlocks = new RenderBlocks(worldObj);
        if(worldObj != null)
        {
        	worldObj.addWorldAccess(this);
            loadRenderers();
//            renderChunksDeep = (entityVehicle.lengthBlocks >> 4) +1;
//            renderChunksTall = (entityVehicle.heightBlocks >> 4) +1;
//            renderChunksWide = (entityVehicle.widthBlocks >> 4) +1;
        }
    }

    public void loadRenderers()
    {
        if(worldObj == null)
        {
            return;
        }
        renderDistance = mc.gameSettings.renderDistance;
        if(worldRenderers != null)
        {
            for(int i = 0; i < worldRenderers.length; i++)
            {
                worldRenderers[i].stopRendering();
            }

        }
        int j = 64 << 3 - renderDistance;
        if(j > 400)
        {
            j = 400;
        }
        renderChunksWide = j / 16 + 1;
        worldObj.getClass();
        renderChunksTall = 128 / 16;
        renderChunksDeep = j / 16 + 1;
        worldRenderers = new WorldRenderer[renderChunksWide * renderChunksTall * renderChunksDeep];
        sortedWorldRenderers = new WorldRenderer[renderChunksWide * renderChunksTall * renderChunksDeep];
        int k = 0;
        int l = 0;
        minBlockX = 0;
        minBlockY = 0;
        minBlockZ = 0;
        maxBlockX = renderChunksWide;
        maxBlockY = renderChunksTall;
        maxBlockZ = renderChunksDeep;
        for(int i1 = 0; i1 < worldRenderersToUpdate.size(); i1++)
        {
            ((WorldRenderer)worldRenderersToUpdate.get(i1)).needsUpdate = false;
        }

        worldRenderersToUpdate.clear();
        tileEntities.clear();
        for(int j1 = 0; j1 < renderChunksWide; j1++)
        {
            for(int k1 = 0; k1 < renderChunksTall; k1++)
            {
                for(int l1 = 0; l1 < renderChunksDeep; l1++)
                {
                    worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1] = new WorldRenderer(worldObj, tileEntities, j1 * 16, k1 * 16, l1 * 16, 16, glRenderListBase + k);
                    if(occlusionEnabled)
                    {
                        worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1].glOcclusionQuery = glOcclusionQueryBase.get(l);
                    }
                    worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1].isWaitingOnOcclusionQuery = false;
                    worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1].isVisible = true;
                    worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1].isInFrustum = true;
                    worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1].chunkIndex = l++;
                    worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1].markDirty();
                    sortedWorldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1] = worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1];
                    worldRenderersToUpdate.add(worldRenderers[(l1 * renderChunksTall + k1) * renderChunksWide + j1]);
                    k += 3;
                }

            }

        }

        if(worldObj != null)
        {
//            Entity entityliving = entityVehicle.getEntityInLocalCoords(mc.renderViewEntity);
        	Entity entityliving = mc.renderViewEntity;
            markRenderersForNewPosition(MathHelper.floor_double(entityliving.posX), MathHelper.floor_double(entityliving.posY), MathHelper.floor_double(entityliving.posZ));
            Arrays.sort(sortedWorldRenderers, new EntitySorter(entityliving));
        }
        renderEntitiesStartupCounter = 2;
    }

    private void markRenderersForNewPosition(int i, int j, int k)
    {
        i -= 8;
        j -= 8;
        k -= 8;
        minBlockX = 0x7fffffff;
        minBlockY = 0x7fffffff;
        minBlockZ = 0x7fffffff;
        maxBlockX = 0x80000000;
        maxBlockY = 0x80000000;
        maxBlockZ = 0x80000000;
        int l = renderChunksWide * 16;
        int i1 = l / 2;
        for(int j1 = 0; j1 < renderChunksWide; j1++)
        {
            int k1 = j1 * 16;
            int l1 = (k1 + i1) - i;
            if(l1 < 0)
            {
                l1 -= l - 1;
            }
            l1 /= l;
            k1 -= l1 * l;
            if(k1 < minBlockX)
            {
                minBlockX = k1;
            }
            if(k1 > maxBlockX)
            {
                maxBlockX = k1;
            }
            for(int i2 = 0; i2 < renderChunksDeep; i2++)
            {
                int j2 = i2 * 16;
                int k2 = (j2 + i1) - k;
                if(k2 < 0)
                {
                    k2 -= l - 1;
                }
                k2 /= l;
                j2 -= k2 * l;
                if(j2 < minBlockZ)
                {
                    minBlockZ = j2;
                }
                if(j2 > maxBlockZ)
                {
                    maxBlockZ = j2;
                }
                for(int l2 = 0; l2 < renderChunksTall; l2++)
                {
                    int i3 = l2 * 16;
                    if(i3 < minBlockY)
                    {
                        minBlockY = i3;
                    }
                    if(i3 > maxBlockY)
                    {
                        maxBlockY = i3;
                    }
                    WorldRenderer worldrenderer = worldRenderers[(i2 * renderChunksTall + l2) * renderChunksWide + j1];
                    boolean flag = worldrenderer.needsUpdate;
                    worldrenderer.setPosition(k1, i3, j2);
                    if(!flag && worldrenderer.needsUpdate)
                    {
                        worldRenderersToUpdate.add(worldrenderer);
                    }
                }

            }

        }

    }

    
    public void markBlocksForUpdate(int i, int j, int k, int l, int i1, int j1)
    {
        int k1 = MathHelper.bucketInt(i, 16);
        int l1 = MathHelper.bucketInt(j, 16);
        int i2 = MathHelper.bucketInt(k, 16);
        int j2 = MathHelper.bucketInt(l, 16);
        int k2 = MathHelper.bucketInt(i1, 16);
        int l2 = MathHelper.bucketInt(j1, 16);
        for(int i3 = k1; i3 <= j2; i3++)
        {
            int j3 = i3 % renderChunksWide;
            if(j3 < 0)
            {
                j3 += renderChunksWide;
            }
            for(int k3 = l1; k3 <= k2; k3++)
            {
                int l3 = k3 % renderChunksTall;
                if(l3 < 0)
                {
                    l3 += renderChunksTall;
                }
                for(int i4 = i2; i4 <= l2; i4++)
                {
                    int j4 = i4 % renderChunksDeep;
                    if(j4 < 0)
                    {
                        j4 += renderChunksDeep;
                    }
                    int k4 = (j4 * renderChunksTall + l3) * renderChunksWide + j3;
                    WorldRenderer worldrenderer = worldRenderers[k4];
                    if(!worldrenderer.needsUpdate)
                    {
                        worldRenderersToUpdate.add(worldrenderer);
                        worldrenderer.markDirty();
                    }
                }

            }

        }

    }
    
	@Override
	public void markBlockAndNeighborsNeedsUpdate(int i, int j, int k) {
		markBlocksForUpdate(i - 1, j - 1, k - 1, i + 1, j + 1, k + 1);

	}

	@Override
	public void markBlockRangeNeedsUpdate(int i, int j, int k, int l, int i1, int j1) 
	{
		 markBlocksForUpdate(i - 1, j - 1, k - 1, l + 1, i1 + 1, j1 + 1);

	}

	@Override
	public void playSound(String s, double d, double d1, double d2, float f, float f1) {
		Vector4f localPos = new Vector4f((float)d,(float)d1,(float)d2, 1F);
		Vector4f parentPos = VehicleUtil.localPosToParent(localPos, entityVehicle.getPosVector3f(), entityVehicle.getRotVector3f());
		renderGlobal.playSound(s, parentPos.x, parentPos.y, parentPos.z, f, f1);
	}

	@Override
	public void spawnParticle(String s, double d, double d1, double d2, double d3, double d4, double d5) {
		Vector4f localPos = new Vector4f((float)d,(float)d1,(float)d2, 1F);
		Vector4f parentPos = VehicleUtil.localPosToParent(localPos, entityVehicle.getPosVector3f(), entityVehicle.getRotVector3f());
		
		Vector4f localDirection = new Vector4f((float)d3,(float)d4,(float)d5, 1F);
		Vector4f parentDirection = VehicleUtil.localPosToParent(localDirection, entityVehicle.getPosVector3f(), entityVehicle.getRotVector3f());
		
		renderGlobal.spawnParticle(s, parentPos.x, parentPos.y, parentPos.z, parentDirection.x, parentDirection.y, parentDirection.z);

	}

	@Override
	public void obtainEntitySkin(Entity entity) {
		renderGlobal.obtainEntitySkin(entity);
	}

    public void releaseEntitySkin(Entity entity)
    {
    	renderGlobal.releaseEntitySkin(entity);
    }

	@Override
	public void playRecord(String s, int i, int j, int k) {
		Vector4f localPos = new Vector4f(i,j,k, 1F);
		Vector4f parentPos = VehicleUtil.localPosToParent(localPos, entityVehicle.getPosVector3f(), entityVehicle.getRotVector3f());
		renderGlobal.playRecord(s, (int)parentPos.x, (int)parentPos.y, (int)parentPos.z);
	}

	@Override
	public void doNothingWithTileEntity(int i, int j, int k, TileEntity tileentity) {
		// do nothing
	}

	@Override
	public void playAuxSFX(EntityPlayer entityplayer, int i, int j, int k, int l, int i1) {
		Vector4f localPos = new Vector4f(j,k,l, 1F);
		Vector4f parentPos = VehicleUtil.localPosToParent(localPos, entityVehicle.getPosVector3f(), entityVehicle.getRotVector3f());
		
		renderGlobal.playAuxSFX(entityplayer, i, (int)parentPos.x, (int)parentPos.y, (int)parentPos.z, i1);
	}

   public int sortAndRender(EntityLiving entitylivingParent, int i, double d)
   {
	   EntityLiving entityliving = entitylivingParent; // entityVehicle.getEntityInLocalCoords(entitylivingParent);
        for(int j = 0; j < 10; j++)
        {
            worldRenderersCheckIndex = (worldRenderersCheckIndex + 1) % worldRenderers.length;
            WorldRenderer worldrenderer = worldRenderers[worldRenderersCheckIndex];
            if(worldrenderer.needsUpdate && !worldRenderersToUpdate.contains(worldrenderer))
            {
                worldRenderersToUpdate.add(worldrenderer);
            }
        }

        if(mc.gameSettings.renderDistance != renderDistance)
        {
            loadRenderers();
        }
        if(i == 0)
        {
            renderersLoaded = 0;
            renderersBeingClipped = 0;
            renderersBeingOccluded = 0;
            renderersBeingRendered = 0;
            renderersSkippingRenderPass = 0;
        }
        double d1 = entityliving.lastTickPosX + (entityliving.posX - entityliving.lastTickPosX) * d;
        double d2 = entityliving.lastTickPosY + (entityliving.posY - entityliving.lastTickPosY) * d;
        double d3 = entityliving.lastTickPosZ + (entityliving.posZ - entityliving.lastTickPosZ) * d;
        double d4 = entityliving.posX - prevSortX;
        double d5 = entityliving.posY - prevSortY;
        double d6 = entityliving.posZ - prevSortZ;
        if(d4 * d4 + d5 * d5 + d6 * d6 > 16D)
        {
            prevSortX = entityliving.posX;
            prevSortY = entityliving.posY;
            prevSortZ = entityliving.posZ;
            markRenderersForNewPosition(MathHelper.floor_double(entityliving.posX), MathHelper.floor_double(entityliving.posY), MathHelper.floor_double(entityliving.posZ));
            Arrays.sort(sortedWorldRenderers, new EntitySorter(entityliving));
        }
        RenderHelper.disableStandardItemLighting();
        int k = 0;
        if(occlusionEnabled && mc.gameSettings.advancedOpengl && !mc.gameSettings.anaglyph && i == 0)
        {
            int l = 0;
            int i1 = 16;
            checkOcclusionQueryResult(l, i1);
            for(int j1 = l; j1 < i1; j1++)
            {
                sortedWorldRenderers[j1].isVisible = true;
            }

            k += renderSortedRenderers(l, i1, i, d);
            do
            {
                int byte0 = i1;
                i1 *= 2;
                if(i1 > sortedWorldRenderers.length)
                {
                    i1 = sortedWorldRenderers.length;
                }
                GL11.glDisable(3553 /*GL_TEXTURE_2D*/);
	            GL11.glDisable(2896 /*GL_LIGHTING*/);
	            GL11.glDisable(3008 /*GL_ALPHA_TEST*/);
	            GL11.glDisable(2912 /*GL_FOG*/);
	            GL11.glColorMask(false, false, false, false);
	            GL11.glDepthMask(false);
	            checkOcclusionQueryResult(byte0, i1);
	            GL11.glPushMatrix();
	            float f = 0.0F;
	            float f1 = 0.0F;
	            float f2 = 0.0F;
	            for(int k1 = byte0; k1 < i1; k1++)
	            {
	                if(sortedWorldRenderers[k1].skipAllRenderPasses())
	                {
	                    sortedWorldRenderers[k1].isInFrustum = false;
	                    continue;
	                }
	                if(!sortedWorldRenderers[k1].isInFrustum)
	                {
	                    sortedWorldRenderers[k1].isVisible = true;
	                }
	                if(!sortedWorldRenderers[k1].isInFrustum || sortedWorldRenderers[k1].isWaitingOnOcclusionQuery)
	                {
	                    continue;
	                }
	                float f3 = MathHelper.sqrt_float(sortedWorldRenderers[k1].distanceToEntitySquared(entityliving));
	                int l1 = (int)(1.0F + f3 / 128F);
	                WorldRenderer worldrenderer1 = sortedWorldRenderers[k1];
	                float f4 = (float)((double)worldrenderer1.posXMinus - d1);
	                float f5 = (float)((double)worldrenderer1.posYMinus - d2);
	                float f6 = (float)((double)worldrenderer1.posZMinus - d3);
	                float f7 = f4 - f;
	                float f8 = f5 - f1;
	                float f9 = f6 - f2;
	                if(f7 != 0.0F || f8 != 0.0F || f9 != 0.0F)
	                {
	                    GL11.glTranslatef(f7, f8, f9);
	                    f += f7;
	                    f1 += f8;
	                    f2 += f9;
	                }
	                ARBOcclusionQuery.glBeginQueryARB(35092 /*GL_SAMPLES_PASSED_ARB*/, sortedWorldRenderers[k1].glOcclusionQuery);
	                sortedWorldRenderers[k1].callOcclusionQueryList();
	                ARBOcclusionQuery.glEndQueryARB(35092 /*GL_SAMPLES_PASSED_ARB*/);
	                sortedWorldRenderers[k1].isWaitingOnOcclusionQuery = true;
	            }
	
	            GL11.glPopMatrix();
	            if(mc.gameSettings.anaglyph)
	            {
	                if(EntityRenderer.anaglyphField == 0)
	                {
	                    GL11.glColorMask(false, true, true, true);
	                } else
	                {
	                    GL11.glColorMask(true, false, false, true);
	                }
	            } else
	            {
	                GL11.glColorMask(true, true, true, true);
	            }
	            GL11.glDepthMask(true);
	            GL11.glEnable(3553 /*GL_TEXTURE_2D*/);
	            GL11.glEnable(3008 /*GL_ALPHA_TEST*/);
	            GL11.glEnable(2912 /*GL_FOG*/);
	            k += renderSortedRenderers(byte0, i1, i, d);
	        } while(i1 < sortedWorldRenderers.length);
	    } else
	    {
	        k += renderSortedRenderers(0, sortedWorldRenderers.length, i, d);
	    }
	    return k;
	}
	
	private int renderSortedRenderers(int i, int j, int k, double d)
	{
	    glRenderLists.clear();
	    int l = 0;
	    for(int i1 = i; i1 < j; i1++)
	    {
	        if(k == 0)
	        {
	            renderersLoaded++;
	            if(sortedWorldRenderers[i1].skipRenderPass[k])
	            {
	                renderersSkippingRenderPass++;
	            } else
	            if(!sortedWorldRenderers[i1].isInFrustum)
	            {
	                renderersBeingClipped++;
	            } else
	            if(occlusionEnabled && !sortedWorldRenderers[i1].isVisible)
	            {
	                renderersBeingOccluded++;
	            } else
	            {
	                renderersBeingRendered++;
	            }
	        }
	        if(sortedWorldRenderers[i1].skipRenderPass[k] || !sortedWorldRenderers[i1].isInFrustum || occlusionEnabled && !sortedWorldRenderers[i1].isVisible)
	        {
	            continue;
	        }
	        int j1 = sortedWorldRenderers[i1].getGLCallListForPass(k);
	        if(j1 >= 0)
	        {
	            glRenderLists.add(sortedWorldRenderers[i1]);
	            l++;
	        }
	    }
	
	    EntityLiving entityliving = mc.renderViewEntity; //entityVehicle.getEntityInLocalCoords(mc.renderViewEntity);
	    double d1 = entityliving.lastTickPosX + (entityliving.posX - entityliving.lastTickPosX) * d;
	    double d2 = entityliving.lastTickPosY + (entityliving.posY - entityliving.lastTickPosY) * d;
	    double d3 = entityliving.lastTickPosZ + (entityliving.posZ - entityliving.lastTickPosZ) * d;
	    int k1 = 0;
	    for(int l1 = 0; l1 < allRenderLists.length; l1++)
	    {
	        allRenderLists[l1].func_859_b();
	    }
	
	    for(int i2 = 0; i2 < glRenderLists.size(); i2++)
	    {
	        WorldRenderer worldrenderer = (WorldRenderer)glRenderLists.get(i2);
	        int j2 = -1;
	        for(int k2 = 0; k2 < k1; k2++)
	        {
	            if(allRenderLists[k2].func_862_a(worldrenderer.posXMinus, worldrenderer.posYMinus, worldrenderer.posZMinus))
	            {
	                j2 = k2;
	            }
	        }
	
	        if(j2 < 0)
	        {
	            j2 = k1++;
	            allRenderLists[j2].func_861_a(worldrenderer.posXMinus, worldrenderer.posYMinus, worldrenderer.posZMinus, d1, d2, d3);
	        }
	        allRenderLists[j2].func_858_a(worldrenderer.getGLCallListForPass(k));
	    }
	
	    renderAllRenderLists(k, d);
	    return l;
	}
	
	public void renderAllRenderLists(int i, double d)
	{
	    mc.entityRenderer.enableLightmap(d);
	    for(int j = 0; j < allRenderLists.length; j++)
	    {
	        allRenderLists[j].func_860_a();
	    }
	
	    mc.entityRenderer.disableLightmap(d);
	}
	
	private void checkOcclusionQueryResult(int i, int j)
	{
	    for(int k = i; k < j; k++)
	    {
	        if(!sortedWorldRenderers[k].isWaitingOnOcclusionQuery)
	        {
	            continue;
	        }
	        occlusionResult.clear();
	        ARBOcclusionQuery.glGetQueryObjectuARB(sortedWorldRenderers[k].glOcclusionQuery, 34919 /*GL_QUERY_RESULT_AVAILABLE_ARB*/, occlusionResult);
	        if(occlusionResult.get(0) != 0)
	        {
	            sortedWorldRenderers[k].isWaitingOnOcclusionQuery = false;
	            occlusionResult.clear();
	            ARBOcclusionQuery.glGetQueryObjectuARB(sortedWorldRenderers[k].glOcclusionQuery, 34918 /*GL_QUERY_RESULT_ARB*/, occlusionResult);
	            sortedWorldRenderers[k].isVisible = occlusionResult.get(0) != 0;
	        }
	    }
	
	}
    public boolean updateRenderers(EntityLiving entitylivingParent, boolean flag)
    {
    	EntityLiving entityliving = entitylivingParent; //entityVehicle.getEntityInLocalCoords(entitylivingParent);
        boolean flag1 = false;
        if(flag1)
        {
            Collections.sort(worldRenderersToUpdate, new RenderSorter(entityliving));
            int i = worldRenderersToUpdate.size() - 1;
            int j = worldRenderersToUpdate.size();
            for(int k = 0; k < j; k++)
            {
                WorldRenderer worldrenderer = (WorldRenderer)worldRenderersToUpdate.get(i - k);
                if(!flag)
                {
                    if(worldrenderer.distanceToEntitySquared(entityliving) > 256F)
                    {
                        if(worldrenderer.isInFrustum)
                        {
                            if(k >= 3)
                            {
                                return false;
                            }
                        } else
                        if(k >= 1)
                        {
                            return false;
                        }
                    }
                } else
                if(!worldrenderer.isInFrustum)
                {
                    continue;
                }
                worldrenderer.updateRenderer();
                worldRenderersToUpdate.remove(worldrenderer);
                worldrenderer.needsUpdate = false;
            }

            return worldRenderersToUpdate.size() == 0;
        }
        byte byte0 = 2;
        RenderSorter rendersorter = new RenderSorter(entityliving);
        WorldRenderer aworldrenderer[] = new WorldRenderer[byte0];
        ArrayList arraylist = null;
        int l = worldRenderersToUpdate.size();
        int i1 = 0;
        for(int j1 = 0; j1 < l; j1++)
        {
            WorldRenderer worldrenderer1 = (WorldRenderer)worldRenderersToUpdate.get(j1);
            if(!flag)
            {
                if(worldrenderer1.distanceToEntitySquared(entityliving) > 256F)
                {
                    int k2;
                    for(k2 = 0; k2 < byte0 && (aworldrenderer[k2] == null || rendersorter.doCompare(aworldrenderer[k2], worldrenderer1) <= 0); k2++) { }
                    if(--k2 <= 0)
                    {
                        continue;
                    }
                    for(int i3 = k2; --i3 != 0;)
                    {
                        aworldrenderer[i3 - 1] = aworldrenderer[i3];
                    }

                    aworldrenderer[k2] = worldrenderer1;
                    continue;
                }
            } else
            if(!worldrenderer1.isInFrustum)
            {
                continue;
            }
            if(arraylist == null)
            {
                arraylist = new ArrayList();
            }
            i1++;
            arraylist.add(worldrenderer1);
            worldRenderersToUpdate.set(j1, null);
        }

        if(arraylist != null)
        {
            if(arraylist.size() > 1)
            {
                Collections.sort(arraylist, rendersorter);
            }
            for(int k1 = arraylist.size() - 1; k1 >= 0; k1--)
            {
                WorldRenderer worldrenderer2 = (WorldRenderer)arraylist.get(k1);
                worldrenderer2.updateRenderer();
                worldrenderer2.needsUpdate = false;
            }

        }
        int l1 = 0;
        for(int i2 = byte0 - 1; i2 >= 0; i2--)
        {
            WorldRenderer worldrenderer3 = aworldrenderer[i2];
            if(worldrenderer3 == null)
            {
                continue;
            }
            if(!worldrenderer3.isInFrustum && i2 != byte0 - 1)
            {
                aworldrenderer[i2] = null;
                aworldrenderer[0] = null;
                break;
            }
            aworldrenderer[i2].updateRenderer();
            aworldrenderer[i2].needsUpdate = false;
            l1++;
        }

        int j2 = 0;
        int l2 = 0;
        for(int j3 = worldRenderersToUpdate.size(); j2 != j3; j2++)
        {
            WorldRenderer worldrenderer4 = (WorldRenderer)worldRenderersToUpdate.get(j2);
            if(worldrenderer4 == null)
            {
                continue;
            }
            boolean flag2 = false;
            for(int k3 = 0; k3 < byte0 && !flag2; k3++)
            {
                if(worldrenderer4 == aworldrenderer[k3])
                {
                    flag2 = true;
                }
            }

            if(flag2)
            {
                continue;
            }
            if(l2 != j2)
            {
                worldRenderersToUpdate.set(l2, worldrenderer4);
            }
            l2++;
        }

        while(--j2 >= l2) 
        {
            worldRenderersToUpdate.remove(j2);
        }
        return l == i1 + l1;
    }
    
    public void clipRenderersByFrustrum(ICamera icamera, float f)
    {
        for(int i = 0; i < worldRenderers.length; i++)
        {
            if(!worldRenderers[i].skipAllRenderPasses() && (!worldRenderers[i].isInFrustum || (i + frustrumCheckOffset & 0xf) == 0))
            {
                worldRenderers[i].updateInFrustrum(icamera);
            }
        }

        frustrumCheckOffset++;
    }

    public void drawBlockBreaking(Entity entityplayer, MovingObjectPosition movingobjectposition, int i, ItemStack itemstack, float f)
    {
        Tessellator tessellator = Tessellator.instance;
        GL11.glEnable(3042 /*GL_BLEND*/);
        GL11.glEnable(3008 /*GL_ALPHA_TEST*/);
        GL11.glBlendFunc(770, 1);
        GL11.glColor4f(1.0F, 1.0F, 1.0F, (MathHelper.sin((float)System.currentTimeMillis() / 100F) * 0.2F + 0.4F) * 0.5F);
        if(i == 0)
        {
            if(damagePartialTime > 0.0F)
            {
                GL11.glBlendFunc(774, 768);
                int j = renderEngine.getTexture("/terrain.png");
                GL11.glBindTexture(3553 /*GL_TEXTURE_2D*/, j);
                GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.5F);
                GL11.glPushMatrix();
                int k = worldObj.getBlockId(movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ);
                Block block = k <= 0 ? null : Block.blocksList[k];
                GL11.glDisable(3008 /*GL_ALPHA_TEST*/);
                GL11.glPolygonOffset(-3F, -3F);
                GL11.glEnable(32823 /*GL_POLYGON_OFFSET_FILL*/);
                double d = entityplayer.lastTickPosX + (entityplayer.posX - entityplayer.lastTickPosX) * (double)f;
                double d1 = entityplayer.lastTickPosY + (entityplayer.posY - entityplayer.lastTickPosY) * (double)f;
                double d2 = entityplayer.lastTickPosZ + (entityplayer.posZ - entityplayer.lastTickPosZ) * (double)f;
                if(block == null)
                {
                    block = Block.stone;
                }
                GL11.glEnable(3008 /*GL_ALPHA_TEST*/);
                tessellator.startDrawingQuads();
                tessellator.setTranslationD(-d, -d1, -d2);
                tessellator.disableColor();
                globalRenderBlocks.renderBlockUsingTexture(block, movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ, 240 + (int)(damagePartialTime * 10F));
                tessellator.draw();
                tessellator.setTranslationD(0.0D, 0.0D, 0.0D);
                GL11.glDisable(3008 /*GL_ALPHA_TEST*/);
                GL11.glPolygonOffset(0.0F, 0.0F);
                GL11.glDisable(32823 /*GL_POLYGON_OFFSET_FILL*/);
                GL11.glEnable(3008 /*GL_ALPHA_TEST*/);
                GL11.glDepthMask(true);
                GL11.glPopMatrix();
            }
        } else
        if(itemstack != null)
        {
            GL11.glBlendFunc(770, 771);
            float f1 = MathHelper.sin((float)System.currentTimeMillis() / 100F) * 0.2F + 0.8F;
            GL11.glColor4f(f1, f1, f1, MathHelper.sin((float)System.currentTimeMillis() / 200F) * 0.2F + 0.5F);
            int l = renderEngine.getTexture("/terrain.png");
            GL11.glBindTexture(3553 /*GL_TEXTURE_2D*/, l);
            int i1 = movingobjectposition.blockX;
            int j1 = movingobjectposition.blockY;
            int k1 = movingobjectposition.blockZ;
            if(movingobjectposition.sideHit == 0)
            {
                j1--;
            }
            if(movingobjectposition.sideHit == 1)
            {
                j1++;
            }
            if(movingobjectposition.sideHit == 2)
            {
                k1--;
            }
            if(movingobjectposition.sideHit == 3)
            {
                k1++;
            }
            if(movingobjectposition.sideHit == 4)
            {
                i1--;
            }
            if(movingobjectposition.sideHit == 5)
            {
                i1++;
            }
        }
        GL11.glDisable(3042 /*GL_BLEND*/);
        GL11.glDisable(3008 /*GL_ALPHA_TEST*/);
    }

    public void drawSelectionBox(Entity entityplayer, MovingObjectPosition movingobjectposition, int i, ItemStack itemstack, float f)
    {
        if(i == 0 && movingobjectposition.typeOfHit == EnumMovingObjectType.TILE)
        {
            GL11.glEnable(3042 /*GL_BLEND*/);
            GL11.glBlendFunc(770, 771);
            GL11.glColor4f(0.0F, 0.0F, 0.0F, 0.4F);
            GL11.glLineWidth(2.0F);
            GL11.glDisable(3553 /*GL_TEXTURE_2D*/);
            GL11.glDepthMask(false);
            float f1 = 0.002F;
            int j = worldObj.getBlockId(movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ);
            if(j > 0)
            {
                Block.blocksList[j].setBlockBoundsBasedOnState(worldObj, movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ);
                double d = entityplayer.lastTickPosX + (entityplayer.posX - entityplayer.lastTickPosX) * (double)f;
                double d1 = entityplayer.lastTickPosY + (entityplayer.posY - entityplayer.lastTickPosY) * (double)f;
                double d2 = entityplayer.lastTickPosZ + (entityplayer.posZ - entityplayer.lastTickPosZ) * (double)f;
                drawOutlinedBoundingBox(Block.blocksList[j].getSelectedBoundingBoxFromPool(worldObj, movingobjectposition.blockX, movingobjectposition.blockY, movingobjectposition.blockZ).expand(f1, f1, f1).getOffsetBoundingBox(-d, -d1, -d2));
            }
            GL11.glDepthMask(true);
            GL11.glEnable(3553 /*GL_TEXTURE_2D*/);
            GL11.glDisable(3042 /*GL_BLEND*/);
        }
    }

    private void drawOutlinedBoundingBox(AxisAlignedBB axisalignedbb)
    {
        Tessellator tessellator = Tessellator.instance;
        tessellator.startDrawing(3);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.minZ);
        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.maxZ);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
        tessellator.draw();
        tessellator.startDrawing(3);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.minZ);
        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.maxZ);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
        tessellator.draw();
        tessellator.startDrawing(1);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.minZ);
        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.minZ);
        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.minZ);
        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
        tessellator.addVertex(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.maxZ);
        tessellator.addVertex(axisalignedbb.minX, axisalignedbb.maxY, axisalignedbb.maxZ);
        tessellator.draw();
    }
    
    
}
